package com.deepblue.image.maker.exception;

import com.deepblue.image.maker.common.CommonResult;
import com.deepblue.image.maker.enums.BusinessEnum;
import com.deepblue.image.maker.util.CommonResultUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.UnexpectedTypeException;
import java.util.Set;

/**
 * @ClassName GlobalExceptionHandler
 * @Description
 * @Author yangxd
 * @Date 2021/8/19 13:47
 * @Version 1.0
 **/
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
    @ExceptionHandler(value = Exception.class)
    public CommonResult<String> handle(Exception e) {
        if (e instanceof BusinessException) {
            //判断异常是否是我们定义的异常
            BusinessException businessException = (BusinessException) e;
            log.error("[BusinessException]---handle error", e);
            return CommonResultUtil.fail(businessException.getCode(), businessException.getMessage());
        } else if (e instanceof UnexpectedTypeException) {
            return handleUnexpectedTypeException((UnexpectedTypeException) e);
        } else {
            log.error("[GlobalExceptionHandle]---handle error", e);
            return CommonResultUtil.fail(BusinessEnum.FAIL.getCode(), BusinessEnum.FAIL.getMsg());
        }
    }

    /**
     * 处理handleUnexpectedTypeException异常
     *
     * @param e
     * @return
     */
    private CommonResult<String> handleUnexpectedTypeException(UnexpectedTypeException e) {
        String message = e.getMessage();
        log.error("[handleUnexpectedTypeException]---handle error {}", message);
        return CommonResultUtil.fail(BusinessEnum.PARAM_ERROR.getCode(), BusinessEnum.PARAM_ERROR.getMsg());
    }

    /**
     * 处理方法异常
     *
     * @param exception 异常
     * @return
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public CommonResult<String> handleMethodArgumentNotValidException(MethodArgumentNotValidException exception) {
        StringBuilder errorInfo = new StringBuilder();
        BindingResult bindingResult = exception.getBindingResult();
        for (int i = 0; i < bindingResult.getFieldErrors().size(); i++) {
            if (i > 0) {
                errorInfo.append(",");
            }
            FieldError fieldError = bindingResult.getFieldErrors().get(i);
            errorInfo.append(fieldError.getField()).append(" :").append(fieldError.getDefaultMessage());
        }
        log.error("[GlobalExceptionHandler]---handle error {}", errorInfo.toString());
        return CommonResultUtil.fail(BusinessEnum.PARAM_ERROR.getCode(), errorInfo.toString());
    }

    /**
     * 处理参数校验异常
     *
     * @param exception 异常
     * @return
     */
    @ExceptionHandler(ConstraintViolationException.class)
    @ResponseBody
    public CommonResult<String> handleConstraintViolationException(ConstraintViolationException exception) {
        StringBuilder errorInfo = new StringBuilder();
        String errorMessage;

        Set<ConstraintViolation<?>> violations = exception.getConstraintViolations();
        for (ConstraintViolation<?> item : violations) {
            errorInfo.append(item.getMessage()).append(",");
        }
        errorMessage = errorInfo.substring(0, errorInfo.toString().length() - 1);
        return CommonResultUtil.fail(BusinessEnum.PARAM_ERROR.getCode(), errorMessage);
    }

}
